package com.CST.service.impl;

import com.CST.common.api.Response;
import com.CST.dto.BaseInComeDTO;
import com.CST.dto.DateDTO;
import com.CST.dto.InSourceDTO;
import com.CST.entity.*;
import com.CST.mapper.cst.BaseCostMapper;
import com.CST.mapper.cst.BaseInComeMapper;
import com.CST.mapper.cst.EtlMzrcMapper;
import com.CST.mapper.cst.EtlZyrcMapper;
import com.CST.mapper.dataplatform.BdOrganizationMapper;
import com.CST.service.IBaseInComeService;
import com.CST.service.IEtlInComeSourceService;
import com.CST.util.ExcelTransfer;
import com.CST.vo.*;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.Month;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class BaseInComeServiceImpl implements IBaseInComeService {

    @Autowired
    private BaseInComeMapper baseInComeMapper;

    @Autowired
    private IEtlInComeSourceService etlInComeSourceService;

    @Autowired
    private BdOrganizationMapper bdOrganizationMapper;

    @Autowired
    private BaseCostMapper baseCostMapper;

    @Autowired
    private EtlMzrcMapper etlMzrcMapper;

    @Autowired
    private EtlZyrcMapper etlZyrcMapper;

    @Override
    public Response listInComeCoefficient(DateDTO dateDTO) {
        List<AllocationCoefficient> allocationCoefficientList = baseInComeMapper.listInComeCoefficient(dateDTO);
        int size = allocationCoefficientList.size();
        System.out.println(size);
        return Response.success(allocationCoefficientList);
    }

    @Override
    public void insertBaseInCome(InSourceDTO inSourceDTO) {
        List<InSourceVO> inSourceVOList = etlInComeSourceService.listInComeSource(inSourceDTO);
        Integer year = inSourceVOList.get(0).getYear();
        int total1 = inSourceVOList.size();//为防止插入字符超过最大数,分批插入
        int fromIndex1 = 0;
        List<InSourceVO> insertList1 = new ArrayList<>();
        for (int i = 0; i < inSourceVOList.size(); i++) {
            InSourceVO item = inSourceVOList.get(i);
            fromIndex1++;
            insertList1.add(item);
            if (fromIndex1 % 20 == 0 && fromIndex1 <= total1) {
                baseInComeMapper.insertBaseInCome(insertList1, year);
                insertList1 = new ArrayList<>();
            }
        }
        if (CollectionUtils.isNotEmpty(insertList1)) {
            baseInComeMapper.insertBaseInCome(insertList1, year);
        }
    }


    @Override
    public List<InSourceVO> listBaseInCome(InSourceDTO inSourceDTO) {
        List<InSourceVO> inSourceVOList = baseInComeMapper.listBaseInCome(inSourceDTO);
        List<InSourceVO> zhaoPing = inSourceVOList.stream().filter(t -> t.getDescription().contains("找平")).collect(Collectors.toList());
        inSourceVOList = inSourceVOList.stream().filter(t -> !t.getDescription().contains("找平")).collect(Collectors.toList());
        inSourceVOList.addAll(zhaoPing);
        return inSourceVOList;
    }

    @Override
    public List<ReportAllBaseCostVO> listBaseCostAndInCome(DateDTO dateDTO) {
        List<ReportAllBaseCostVO> reportAllBaseCostVOS = baseInComeMapper.listBaseCostAndInCome(dateDTO);
        return reportAllBaseCostVOS;
    }

    /**
     * 科室项目收入分析报表
     * 需要时间范围+父级科室+开单or执行收入标记
     * dateDTO.unitCode = bill为开单
     * dateDTO.unitCode = exe为执行
     *
     * @param dateDTO   时间范围等其他条件
     * @param pDeptCode 父级科室编号
     * @return
     */
    @Override
    public List<BaseInCome> listInComeByDateAndPDeptWith(DateDTO dateDTO, String pDeptCode) {
        List<BaseInCome> list = baseInComeMapper.listInComeByDateAndPDeptWithFee(dateDTO, pDeptCode);
        return list;
    }

    /**
     * 科室收入分析
     * 根据父级科室编号+时间范围计算其子科室的各项收入类型
     * 包括：
     * 1.开单收入
     * 2.本执本开
     * 3.他开本执
     * 1+3.合计收入
     * 2+3.小计
     */
    @Override
    public List<ReportInComeAnalyseVO> listInComeByDateAndPDeptWithAnalyse(DateDTO dateDTO, String pDeptCode) {
        // 获取父级科室收入数据
        List<BaseInCome> baseInComeList = baseInComeMapper.listBaseInComeByDateAndPDept(dateDTO, pDeptCode);
        // 获取父级科室对应的所有子科室
        List<BdOrganization> bdOrganizationList = bdOrganizationMapper.listParentDeptGroup("1");
        List<BdOrganization> pDeptList = bdOrganizationList.stream().filter(t -> pDeptCode.equals(t.getPDeptCode())).collect(Collectors.toList());
        List<ReportInComeAnalyseVO> list = this.packageInComeData(pDeptList, baseInComeList, pDeptCode);
        return list;
    }

    /**
     * 根据时间范围+父级科室编号计算各个子科室收益
     * 用于科室收益分析
     * 收益 = (开单+执行收入)-科室成本
     *
     * @param dateDTO
     * @param pDeptCode
     * @return
     */
    @Override
    public List<ReportBusinessVO> listDeptProfitByDateAndPDept(DateDTO dateDTO, String pDeptCode) {
        BigDecimal one = BigDecimal.ONE;
        List<ReportBusinessVO> reportBusinessVOList = new ArrayList<>();
        // 收入
        List<BaseInCome> baseInComeList = baseInComeMapper.listBaseInComeByDateAndPDept(dateDTO, pDeptCode);
        // 成本
        List<BaseCostVO> baseCostVOList = baseCostMapper.listBaseCostWithPDept(dateDTO, pDeptCode);
        // 计算总收益
        BigDecimal totalInCome = baseInComeList.stream().map(t -> t.getAmount()).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal totalCost = baseCostVOList.stream().map(t -> t.getAmount()).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal totalProfit = totalInCome.subtract(totalCost);
        // 获取父级科室对应的所有子科室
        List<BdOrganization> bdOrganizationList = bdOrganizationMapper.listParentDeptGroup("1");
        List<BdOrganization> pDeptList = bdOrganizationList.stream().filter(t -> pDeptCode.equals(t.getPDeptCode())).collect(Collectors.toList());
        for (int i = 0; i < pDeptList.size(); i++) {
            BdOrganization bdOrganization = pDeptList.get(i);
            ReportBusinessVO reportBusinessVO = new ReportBusinessVO();
            String deptCode = bdOrganization.getDeptCode();
            String deptName = bdOrganization.getDeptName();
            reportBusinessVO.setDeptCode(deptCode);
            reportBusinessVO.setDeptName(deptName);
            // 获取开单+执行收入
            BigDecimal inComeAmount = baseInComeList.stream().filter(t -> deptCode.equals(t.getBillDeptCode()) || deptCode.equals(t.getExecutiveDeptCode())).map(t -> t.getAmount()).reduce(BigDecimal.ZERO, BigDecimal::add);
            // 获取科室成本
            BigDecimal costAmount = baseCostVOList.stream().filter(t -> deptCode.equals(t.getDeptCode())).map(t -> t.getAmount()).reduce(BigDecimal.ZERO, BigDecimal::add);
            // 收益
            BigDecimal profit = inComeAmount.subtract(costAmount);
            reportBusinessVO.setProceeds(profit);
            reportBusinessVOList.add(reportBusinessVO);
            // 计算占比
            if (totalProfit.compareTo(new BigDecimal(0)) != 0) {
                if (i == pDeptList.size() - 1) {
                    reportBusinessVO.setProceedProportion(one.multiply(new BigDecimal(100)));
                } else {
                    BigDecimal divide = profit.divide(totalProfit, 4);
                    one = one.subtract(divide);
                    reportBusinessVO.setProceedProportion(divide.multiply(new BigDecimal(100)));
                }
            }
        }
        return reportBusinessVOList;
    }

    @Override
    public List<ReportBusinessVO> listDeptProfitCompositionByDateAndPDept(DateDTO dateDTO, String pDeptCode) {
        List<ReportBusinessVO> list = new ArrayList<>();
        // 获取收入数据
        List<BaseInComeVO> baseInComeVOList = baseInComeMapper.listBaseInComeVOByDateAndPDept(dateDTO, pDeptCode);
        // 获取成本数据
        List<BaseCostVO> baseCostVOList = baseCostMapper.listBaseCostWithPDept(dateDTO, pDeptCode);
        // 计算住院收益
        ReportBusinessVO zy = this.countProcess(baseInComeVOList, baseCostVOList, "zy");
        list.add(zy);
        // 计算门诊收益
        ReportBusinessVO mz = this.countProcess(baseInComeVOList, baseCostVOList, "mz");
        list.add(mz);
        // 计算医技收益
        ReportBusinessVO yj = this.countProcess(baseInComeVOList, baseCostVOList, "yj");
        list.add(yj);
        // 计算占比
        BigDecimal total = list.stream().map(t -> t.getProceeds()).reduce(BigDecimal.ZERO, BigDecimal::add);
        for (ReportBusinessVO reportBusinessVO : list) {
            BigDecimal proceeds = reportBusinessVO.getProceeds();
            if (total.compareTo(new BigDecimal(0)) != 0) {
                reportBusinessVO.setProceedProportion(proceeds.divide(total, 4).multiply(new BigDecimal(100)));
            }
        }
        return list;
    }


    /**
     * 科室收入项目分析明细
     * 传入时间+父级科室+项目编号
     * 查询明细
     * 通过unitCode控制开单和执行
     */
    @Override
    public List<BaseInComeVO> listBaseInComeVOByDateAndPDeptGroupWithDeptAndFee(DateDTO dateDTO, String pDeptCode, String deptCode, String feeCode) {
        List<BaseInComeVO> list = baseInComeMapper.listBaseInComeVOByDateAndPDeptGroupWithDeptAndFee(dateDTO, pDeptCode, deptCode, feeCode);
        return list;
    }

    /**
     * 保本点分析
     *
     * @param dateDTO   时间条件
     * @param pDeptCode 科室
     * @param type      类型：2住院，1门诊，3医技
     * @return
     */
    @Override
    public List<ReportPointVO> pointAnalysis(DateDTO dateDTO, String pDeptCode, Integer type) {
        List<ReportPointVO> reportPointVOList = new ArrayList<>();
        // 获取收入
        List<BaseInComeVO> baseInComeVOList = baseInComeMapper.listBaseInComeByDateAndPDeptAndType(dateDTO, pDeptCode, null);
        // 获取成本
        List<BaseCostVO> baseCostVOList = baseCostMapper.listBaseCostWithPDept(dateDTO, pDeptCode);
        // 获取对应的组织关系
        List<BdOrganization> bdOrganizationList = bdOrganizationMapper.listGroupByDeptAndPDeptWithType(pDeptCode, null);
        bdOrganizationList = bdOrganizationList.stream().filter(t -> type.toString().equals(t.getClinicalPropertyID())).collect(Collectors.toList());
        for (BdOrganization bdOrganization : bdOrganizationList) {
            ReportPointVO reportPointVO = new ReportPointVO();
            reportPointVO.setDeptCode(bdOrganization.getDeptCode());
            reportPointVO.setDeptName(bdOrganization.getDeptName());
            String deptCode = bdOrganization.getDeptCode();
            List<BaseInComeVO> inComeVOList = baseInComeVOList.stream().filter(t -> deptCode.equals(t.getBillDeptCode()) || deptCode.equals(t.getExecutiveDeptCode())).collect(Collectors.toList());
            List<BaseCostVO> costVOList = baseCostVOList.stream().filter(t -> deptCode.equals(t.getDeptCode())).collect(Collectors.toList());
            // 计算总收入
            BigDecimal totalInCome = inComeVOList.stream().map(t -> t.getAmount()).reduce(BigDecimal.ZERO, BigDecimal::add);
            reportPointVO.setTotalInCome(totalInCome);
            // 计算总成本
            BigDecimal totalCost = costVOList.stream().map(t -> t.getAmount()).reduce(BigDecimal.ZERO, BigDecimal::add);
            reportPointVO.setTotalInCome(totalInCome);
            reportPointVO.setPointInCome(totalCost);
            // 计算总收益
            BigDecimal totalProceeds = totalInCome.subtract(totalCost);
            reportPointVO.setTotalProceeds(totalProceeds);
            // 根据类型计算门诊/住院/医技人次
            BigDecimal number = BigDecimal.ZERO;
            if (type.toString().equals("1") || type.equals("2")) {
                number = this.countNumberByType(dateDTO, pDeptCode, deptCode, type);
            } else {
                number = this.countNumberByType(baseInComeVOList, deptCode, type);
            }
            if (totalCost.compareTo(new BigDecimal(0)) != 0 && totalInCome.compareTo(BigDecimal.ZERO) != 0) {
                BigDecimal point = totalCost.divide(totalInCome.divide(number, 4), 4);
                reportPointVO.setPointCount(point);
            }
            reportPointVOList.add(reportPointVO);
        }
        return reportPointVOList;
    }

    @Override
    public boolean addBaseInCome(BaseInComeDTO dto) {
        BaseInCome base = new BaseInCome();
        BeanUtils.copyProperties(dto, base);
        LocalDate time = dto.getTime();
        int year = time.getYear();
        int month = time.getMonth().getValue();
        base.setYear(year);
        base.setMonth(month);
        base.setOperDtime(time.toString());
        if (base.getId() != null) {
            int oldYear = dto.getOldTime().getYear();
            if (oldYear != base.getYear()) {
                remove(base.getId(), oldYear);
                base.setId(null);
            }
        }
        return base.getId() == null ? baseInComeMapper.insertBaseInComeOne(base) : baseInComeMapper.updateBaseInComeOne(base);
    }

    @Override
    public boolean remove(long id, int year) {
        return baseInComeMapper.deleteOne(id, year);
    }

    /**
     * 整理收入
     * 1.开单收入
     * 2.本执本开
     * 3.他开本执
     * 1+3.合计收入
     * 2+3.小计
     */
    private List<ReportInComeAnalyseVO> packageInComeData(List<BdOrganization> bdOrganizationList, List<BaseInCome> baseInComeList, String pDeptCode) {
        List<ReportInComeAnalyseVO> list = new ArrayList<>();
        for (BdOrganization bdOrganization : bdOrganizationList) {
            String deptCode = bdOrganization.getDeptCode();
            String deptName = bdOrganization.getDeptName();
            ReportInComeAnalyseVO reportInComeAnalyseVO = new ReportInComeAnalyseVO();
            reportInComeAnalyseVO.setDeptCode(deptCode);
            reportInComeAnalyseVO.setDeptName(deptName);
            // 计算开单收入 1
            BigDecimal bill = baseInComeList.stream().filter(t -> deptCode.equals(t.getBillDeptCode())).map(t -> t.getAmount()).reduce(BigDecimal.ZERO, BigDecimal::add);
            // 计算本执本开收入 2
            BigDecimal thisBillThisExe = baseInComeList.stream().filter(t -> deptCode.equals(t.getBillDeptCode()) && deptCode.equals(t.getExecutiveDeptCode())).map(t -> t.getAmount()).reduce(BigDecimal.ZERO, BigDecimal::add);
            // 计算他开本执收入 3
            BigDecimal otherBillThisExe = baseInComeList.stream().filter(t -> !deptCode.equals(t.getBillDeptCode()) && deptCode.equals(t.getExecutiveDeptCode())).map(t -> t.getAmount()).reduce(BigDecimal.ZERO, BigDecimal::add);
            // 合计收入 1+3
            BigDecimal totalInCome = bill.add(otherBillThisExe);
            // 执行合计 2+3
            BigDecimal totalExe = thisBillThisExe.add(otherBillThisExe);
            reportInComeAnalyseVO.setBill(bill);
            reportInComeAnalyseVO.setThisBillThisExe(thisBillThisExe);
            reportInComeAnalyseVO.setOtherBillThisExe(otherBillThisExe);
            reportInComeAnalyseVO.setTotalInCome(totalInCome);
            reportInComeAnalyseVO.setTotalExe(totalExe);
            list.add(reportInComeAnalyseVO);
        }
        return list;
    }

    /**
     * 根据传入值计算门诊，住院，医技收益，用于收益构成分析
     * type传入zy，mz，yj分别的对应 住院，门诊，医技
     */
    private ReportBusinessVO countProcess(List<BaseInComeVO> inComeVOList, List<BaseCostVO> costVOList, String type) {
        List<BaseInComeVO> inList = null;
        List<BaseCostVO> costList = null;
        ReportBusinessVO reportBusinessVO = new ReportBusinessVO();
        switch (type) {
            case "zy":
                reportBusinessVO.setDeptName("住院");
                inList = inComeVOList.stream().filter(t -> "2".equals(t.getBillPropertyId()) || "2".equals(t.getExePropertyId())).collect(Collectors.toList());
                costList = costVOList.stream().filter(t -> "2".equals(t.getClinicalPropertyID())).collect(Collectors.toList());
                break;
            case "mz":
                reportBusinessVO.setDeptName("门诊");
                inList = inComeVOList.stream().filter(t -> "1".equals(t.getBillPropertyId()) || "1".equals(t.getExePropertyId())).collect(Collectors.toList());
                costList = costVOList.stream().filter(t -> "1".equals(t.getClinicalPropertyID())).collect(Collectors.toList());
                break;
            case "yj":
                reportBusinessVO.setDeptName("医技");
                inList = inComeVOList.stream().filter(t -> "02".equals(t.getBillTypeId()) || "02".equals(t.getExeTypeId())).collect(Collectors.toList());
                costList = costVOList.stream().filter(t -> "02".equals(t.getDeptTypeId())).collect(Collectors.toList());
                break;
        }
        BigDecimal in = inList.stream().map(t -> t.getAmount()).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal cost = costList.stream().map(t -> t.getAmount()).reduce(BigDecimal.ZERO, BigDecimal::add);
        // 收益
        BigDecimal process = in.subtract(cost);
        reportBusinessVO.setProceeds(process);
        return reportBusinessVO;
    }

    /**
     * 可传入父级/子级科室
     * 用于计算 1门诊，2住院，3医技 人次
     * 根据type决定
     *
     * @return
     */
    private BigDecimal countNumberByType(DateDTO dateDTO, String pDeptCode, String deptCode, Integer type) {
        // 门诊 or 住院的renci
        List<RcNumberVO> list = new ArrayList();
        switch (type) {
            case 1:
                list = etlMzrcMapper.listMzrcByDateAndPDeptAndDeptGroupPDeptAndDept(dateDTO, pDeptCode, deptCode);
                break;
            case 2:
                list = etlZyrcMapper.listZyrcByDateAndPDeptAndDeptGroupPDeptAndDept(dateDTO, pDeptCode, deptCode);
                break;
        }
        BigDecimal number = list.stream().map(t -> t.getNumber()).reduce(BigDecimal.ZERO, BigDecimal::add);
        return number;
    }

    /**
     * 重载方法，以上只能计算门诊/住院
     * 重载用于计算医技
     */
    private BigDecimal countNumberByType(List<BaseInComeVO> baseInComeVOList, String deptCode, Integer type) {
        int size = baseInComeVOList.stream().filter(t -> deptCode.equals(t.getExecutiveDeptCode())).collect(Collectors.toList()).size();
        return new BigDecimal(size);
    }

    /**
     * 2022/08/29
     * 收入采集
     * xnd
     *
     * @param inSourceDTO
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void insertBaseInComeNew(InSourceDTO inSourceDTO) {
        new Thread(() -> {
            List<InSourceVO> inSourceVOList = etlInComeSourceService.listInComeSourceNew(inSourceDTO);
            Integer year = inSourceDTO.getYear();
            baseInComeMapper.deleteBaseIncome(inSourceDTO);
            //为防止插入字符超过最大数,分批插入
            int total1 = inSourceVOList.size();
            int fromIndex1 = 0;
            List<InSourceVO> insertList1 = new ArrayList<>();
            for (int i = 0; i < inSourceVOList.size(); i++) {
                InSourceVO item = inSourceVOList.get(i);
                fromIndex1++;
                insertList1.add(item);
                if (fromIndex1 % 20 == 0 && fromIndex1 <= total1) {
                    baseInComeMapper.insertBaseInCome(insertList1, year);
                    insertList1 = new ArrayList<>();
                }
            }
            if (CollectionUtils.isNotEmpty(insertList1)) {
                baseInComeMapper.insertBaseInCome(insertList1, year);
            }

        }).start();

    }
    @Autowired
    private ExcelTransfer<ReportAllBaseCostVO> excelTransfer3;
    @Override
    public void exportExcel(HttpServletResponse response, DateDTO dateDTO) throws IOException {
        List<ExcelVO> excel = new ArrayList<>();
        // head
        List<String> strings = new ArrayList<>();
        strings.add("直接成本");
        strings.add("间接成本");
        strings.add("全成本");
        List<String> info = new ArrayList<>();
        info.add("科室代码");
        info.add("科室名称");
        List<ExcelHead> excelHeads = new ArrayList<>();
        excelHeads.add(ExcelHead.builder().head("基本信息").cHead(info).build());
        List<String> info1 = new ArrayList<>();
        info1.add("合计收入(①+③)");
        excelHeads.add(ExcelHead.builder().head("合计收入(①+③)").cHead(info1).build());
        List<String> info2 = new ArrayList<>();
        info2.add("开单收入①");
        excelHeads.add(ExcelHead.builder().head("开单收入①").cHead(info2).build());
        List<String> info3 = new ArrayList<>();
        info3.add("本开本执②");
        info3.add("他开本执③");
        info3.add("小计(②+③)");
        excelHeads.add(ExcelHead.builder().head("执行收入").cHead(info3).build());
        excelHeads.add(ExcelHead.builder().head("人员经费").cHead(strings).build());
        excelHeads.add(ExcelHead.builder().head("药品费用").cHead(strings).build());
        excelHeads.add(ExcelHead.builder().head("卫生材料费用").cHead(strings).build());
        excelHeads.add(ExcelHead.builder().head("固定资产折旧费").cHead(strings).build());
        excelHeads.add(ExcelHead.builder().head("无形资产折旧费").cHead(strings).build());
        excelHeads.add(ExcelHead.builder().head("提取医疗风险基金").cHead(strings).build());
        excelHeads.add(ExcelHead.builder().head("其他费用").cHead(strings).build());
        excelHeads.add(ExcelHead.builder().head("合计").cHead(strings).build());
        List<List<String>> heads = getHead(excelHeads);
        // data
        List<List<Object>> otherData = new ArrayList<>();
        List<ReportAllBaseCostVO> dataInfo =listBaseCostAndInCome(dateDTO);
        dataInfo.forEach(e -> {
            List<Object> list = new ArrayList<>();
            list.add(e.getPDeptCode());
            list.add(e.getPDeptName());
            list.add(e.getTotalInCome());
            list.add(e.getBill());
            list.add(e.getThisBillThisExe1() );
            list.add(e.getOtherBillThisExe1());
            list.add(e.getTotalExe());
            list.add(e.getDirectPersonnel());
            list.add(e.getIndirectPersonnel());
            list.add(e.getTotalPersonnel());
            list.add(e.getDirectDrug());
            list.add(e.getIndirectDrug());
            list.add(e.getTotalDrug());
            list.add(e.getDirectSanitaryMaterials());
            list.add(e.getIndirectSanitaryMaterials());
            list.add(e.getTotalSanitaryMaterials());
            list.add(e.getDirectFixed());
            list.add(e.getIndirectFixed());
            list.add(e.getTotalFixed());
            list.add(e.getDirectIntangible());
            list.add(e.getIndirectIntangible());
            list.add(e.getTotalIntangible());
            list.add(e.getDirectRisk());
            list.add(e.getIndirectRisk());
            list.add(e.getTotalRisk());
            list.add(e.getDirectOther());
            list.add(e.getIndirectOther());
            list.add(e.getTotalOther());
            list.add(e.getDirectSum());
            list.add(e.getIndirectSum());
            list.add(e.getTotalSum());
            otherData.add(list);
        });
        List<List<Object>> otherData1 = new ArrayList<>();
        List<ReportAllBaseCostVO> dataInfo1 =getList(dateDTO);
        dataInfo1.forEach(e -> {
            List<Object> list = new ArrayList<>();
            list.add(e.getDeptCode());
            list.add(e.getDeptName());
            list.add(e.getTotalInCome());
            list.add(e.getBill());
            list.add(e.getThisBillThisExe1() );
            list.add(e.getOtherBillThisExe1());
            list.add(e.getTotalExe());
            list.add(e.getDirectPersonnel());
            list.add(e.getIndirectPersonnel());
            list.add(e.getTotalPersonnel());
            list.add(e.getDirectDrug());
            list.add(e.getIndirectDrug());
            list.add(e.getTotalDrug());
            list.add(e.getDirectSanitaryMaterials());
            list.add(e.getIndirectSanitaryMaterials());
            list.add(e.getTotalSanitaryMaterials());
            list.add(e.getDirectFixed());
            list.add(e.getIndirectFixed());
            list.add(e.getTotalFixed());
            list.add(e.getDirectIntangible());
            list.add(e.getIndirectIntangible());
            list.add(e.getTotalIntangible());
            list.add(e.getDirectRisk());
            list.add(e.getIndirectRisk());
            list.add(e.getTotalRisk());
            list.add(e.getDirectOther());
            list.add(e.getIndirectOther());
            list.add(e.getTotalOther());
            list.add(e.getDirectSum());
            list.add(e.getIndirectSum());
            list.add(e.getTotalSum());
            otherData1.add(list);
        });

        excel.add(ExcelVO.builder().sheet("sheet").listsHead(heads).listsData(otherData).build());
        excel.add(ExcelVO.builder().sheet("sheet1").listsHead(heads).listsData(otherData1).build());
        excelTransfer3.exportExcel(response, "业务科室收支汇总表", excel);
    }


    @Override
    public void exportExcel1(HttpServletResponse response, DateDTO dateDTO) throws IOException {
        List<ExcelVO> excel = new ArrayList<>();
        // head
        List<String> strings = new ArrayList<>();
        strings.add("直接成本");
        strings.add("间接成本");
        strings.add("全成本");
        List<String> info = new ArrayList<>();
        info.add("科室代码");
        info.add("科室名称");
        List<ExcelHead> excelHeads = new ArrayList<>();
        excelHeads.add(ExcelHead.builder().head("基本信息").cHead(info).build());
        List<String> info1 = new ArrayList<>();
        info1.add("合计收入(①+③)");
        excelHeads.add(ExcelHead.builder().head("合计收入(①+③)").cHead(info1).build());
        List<String> info2 = new ArrayList<>();
        info2.add("开单收入①");
        excelHeads.add(ExcelHead.builder().head("开单收入①").cHead(info2).build());
        List<String> info3 = new ArrayList<>();
        info3.add("本开本执②");
        info3.add("他开本执③");
        info3.add("小计(②+③)");
        excelHeads.add(ExcelHead.builder().head("执行收入").cHead(info3).build());
        excelHeads.add(ExcelHead.builder().head("人员经费").cHead(strings).build());
        excelHeads.add(ExcelHead.builder().head("药品费用").cHead(strings).build());
        excelHeads.add(ExcelHead.builder().head("卫生材料费用").cHead(strings).build());
        excelHeads.add(ExcelHead.builder().head("固定资产折旧费").cHead(strings).build());
        excelHeads.add(ExcelHead.builder().head("无形资产折旧费").cHead(strings).build());
        excelHeads.add(ExcelHead.builder().head("提取医疗风险基金").cHead(strings).build());
        excelHeads.add(ExcelHead.builder().head("其他费用").cHead(strings).build());
        excelHeads.add(ExcelHead.builder().head("合计").cHead(strings).build());
        List<List<String>> heads = getHead(excelHeads);
        // data
        List<List<Object>> otherData = new ArrayList<>();
        List<ReportAllBaseCostVO> dataInfo =this.listALLBaseCostByZDept(dateDTO);
        dataInfo.forEach(e -> {
            List<Object> list = new ArrayList<>();
            list.add(e.getPDeptCode());
            list.add(e.getPDeptName());
            list.add(e.getTotalInCome());
            list.add(e.getBill());
            list.add(e.getThisBillThisExe1() );
            list.add(e.getOtherBillThisExe1());
            list.add(e.getTotalExe());
            list.add(e.getDirectPersonnel());
            list.add(e.getIndirectPersonnel());
            list.add(e.getTotalPersonnel());
            list.add(e.getDirectDrug());
            list.add(e.getIndirectDrug());
            list.add(e.getTotalDrug());
            list.add(e.getDirectSanitaryMaterials());
            list.add(e.getIndirectSanitaryMaterials());
            list.add(e.getTotalSanitaryMaterials());
            list.add(e.getDirectFixed());
            list.add(e.getIndirectFixed());
            list.add(e.getTotalFixed());
            list.add(e.getDirectIntangible());
            list.add(e.getIndirectIntangible());
            list.add(e.getTotalIntangible());
            list.add(e.getDirectRisk());
            list.add(e.getIndirectRisk());
            list.add(e.getTotalRisk());
            list.add(e.getDirectOther());
            list.add(e.getIndirectOther());
            list.add(e.getTotalOther());
            list.add(e.getDirectSum());
            list.add(e.getIndirectSum());
            list.add(e.getTotalSum());
            otherData.add(list);
        });
        excel.add(ExcelVO.builder().sheet("sheet").listsHead(heads).listsData(otherData).build());
        excelTransfer3.exportExcel(response, "住院科室收支汇总表", excel);
    }

    @Override
    public List<ReportAllBaseCostVO> listALLBaseCostByZDept(DateDTO dateDTO) {

        List<ReportAllBaseCostVO> reportAllBaseCostVOS = baseInComeMapper.listALLBaseCostByZDept(dateDTO);

        return reportAllBaseCostVOS;
    }






    @Override
    public List<ReportAllBaseCostVO> test(DateDTO dateDTO) {
        return this.getList(dateDTO);
    }

    private List<List<String>> getHead(List<ExcelHead> headList) {
        List<List<String>> lists = new ArrayList<>();
        headList.forEach(e -> e.getCHead().forEach(c -> {
            List<String> list = new ArrayList<>();
            list.add(e.getHead());
            list.add(c);
            lists.add(list);
        }));
        return lists;
    }

    private  List<ReportAllBaseCostVO>  getList(DateDTO dateDTO){
        //成本
        List<ReportAllBaseCostVO> reportAllBaseCostVOS = baseInComeMapper.listAllBaseCost(dateDTO);
        //收入
        List<ReportAllBaseCostVO> reportAllBaseCostVOS1 = baseInComeMapper.listAllInCome(dateDTO);
        for (ReportAllBaseCostVO reportAllBaseCostVO : reportAllBaseCostVOS) {
            ReportAllBaseCostVO reportAllBaseCostVO1 = reportAllBaseCostVOS1.stream().filter(t -> t.getDeptCode().equals(reportAllBaseCostVO.getDeptCode())
                    && t.getPDeptCode().equals(reportAllBaseCostVO.getPDeptCode())).findFirst().orElse(null);
            reportAllBaseCostVO.setBill(reportAllBaseCostVO1.getBill());
            reportAllBaseCostVO.setTotalInCome(reportAllBaseCostVO1.getTotalInCome());
            reportAllBaseCostVO.setOtherBillThisExe1(reportAllBaseCostVO1.getOtherBillThisExe1());
            reportAllBaseCostVO.setThisBillThisExe1(reportAllBaseCostVO1.getThisBillThisExe1());
            reportAllBaseCostVO.setTotalExe(reportAllBaseCostVO1.getTotalExe());
        }
    return reportAllBaseCostVOS;
    }



}
